package com.gci.lib_markdown_editor.editor

import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.graphics.Color
import android.os.CountDownTimer
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.*
import com.gci.lib_markdown_editor.R
import com.gci.lib_markdown_editor.databinding.LayoutEditorViewBinding
import com.gci.lib_markdown_editor.isKeyboardConnected
import com.jhonjson.dialoglib.BottomListDialog
import java.io.File
class EditorView constructor(
        context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs), View.OnClickListener {
    private var isNormal: Boolean = false
    private lateinit var _binding: LayoutEditorViewBinding
    private val binding get() = _binding
    private var cacheText: String? = null
    private var cache: ArrayList<String> = ArrayList()

    private val countDownTime = object :CountDownTimer(1000,100){
        override fun onTick(millisUntilFinished: Long) {

        }

        override fun onFinish() {
            val text = binding.editText.text.toString()

        }

    }

    
    lateinit var activity: Activity

    //font size
    var fs: Float = 14.toFloat()
        set(value) {
            field = value
            binding.editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, field)
        }

    //attributes
    private var isEditorView = true

    lateinit var listener: OnClickListener
    var outputFile: File? = null

    interface OnClickListener {
        fun onAddImageClick(curPosition: Int)
        fun onNewColumnAdd(toString: String)
    }

    init {
        _binding = LayoutEditorViewBinding.inflate(LayoutInflater.from(context))
        
        with(binding) {
            btnHeader.setOnClickListener(this@EditorView)
            btnList.setOnClickListener(this@EditorView)
            btnQuote.setOnClickListener(this@EditorView)
            btnImage.setOnClickListener(this@EditorView)
            btnText.setOnClickListener(this@EditorView)
            btnCode.setOnClickListener(this@EditorView)
            btnUrl.setOnClickListener(this@EditorView)
            btnLine.setOnClickListener(this@EditorView)
            btnTop.setOnClickListener(this@EditorView)
            btnBottom.setOnClickListener(this@EditorView)

            binding.editText.setOnKeyListener { v, keyCode, event ->
                if (keyCode == KeyEvent.KEYCODE_ENTER) {
                    saveMarkdownFile(outputFile!!)
                    cache.add(binding.editText.text.toString())
                    listener.onNewColumnAdd(binding.editText.text.toString())
                }
                false

            }

            binding.editText.addTextChangedListener(object : TextWatcher {
                override fun afterTextChanged(s: Editable?) {
                    outputFile?.let { saveMarkdownFile(outputFile!!) }
                }

                override fun beforeTextChanged(
                    s: CharSequence?,
                    start: Int,
                    count: Int,
                    after: Int
                ) {

                }

                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

                }

            })
        }
        addView(binding.root)
    }


    fun saveMarkdownFile(file: File) {
        if (!file.exists())
            file.createNewFile()
        file.writeText(binding.editText.text.toString())
    }

    fun saveTempChange(file: File?) {
        file?.writeText(binding.editText.text.toString())
    }

    override fun onClick(v: View?) {
        saveTempChange(outputFile)
        val lines = binding.editText.text.toString().split("\n")
        var lastLine = lines[lines.lastIndex]
        if (lastLine.isNotEmpty()) {
            binding.editText.append("\n\n")
            gotoBottom()
        }

        when (v) {
            binding.btnHeader -> {
                binding.editText.requestFocus()
                val curPosition = binding.editText.selectionStart
                val headers = resources.getStringArray(R.array.headers)
                BottomListDialog.Builder(context)
                        .addMenuListItem(headers) { position: Int ->
                            when (position) {
                                0 -> {
                                    binding.editText.append("# ")
                                    binding.editText.setSelection(curPosition + 2)
                                }
                                1 -> {
                                    binding.editText.append("## ")
                                    binding.editText.setSelection(curPosition + 3)
                                }
                                2 -> {
                                    binding.editText.append("### ")
                                    binding.editText.setSelection(curPosition + 4)
                                }
                            }
                            binding.editText.showKeyBoard(activity)
                        }
                        .show()
            }

            binding.btnList -> {

                if (lines.size > 1 && lastLine.isEmpty()) {

                    lastLine = lines[lines.lastIndex - 1]
                }
                var isOrder = false
                var lastOrderIndex = 0
                if (lastLine.matches("^\\d+\\. .*".toRegex())) {
                    lastOrderIndex = lastLine.substringBefore(".").toInt()
                } else {
                    lastOrderIndex = 0
                }
                val curPosition = binding.editText.selectionStart
                val listStyle = resources.getStringArray(R.array.list)
                BottomListDialog.Builder(context)
                        .addMenuListItem(listStyle) { pos: Int ->
                            when (pos) {
                                0 -> {
                                    val promote = "${lastOrderIndex + 1}. "
                                    binding.editText.append("${lastOrderIndex + 1}. ")
                                    binding.editText.setSelection(curPosition + promote.length)
                                }
                                1 -> {
                                    binding.editText.append("+ ")
                                    binding.editText.setSelection(curPosition + 2)
                                }
                            }
                            binding.editText.showKeyBoard(activity)
                        }
                        .show()
            }

            binding.btnText -> {
                val curPosition = binding.editText.selectionStart
                val titls = resources.getStringArray(R.array.text)
                BottomListDialog.Builder(context)
                        .addMenuListItem(titls) { pos: Int ->
                            when (pos) {
                                0 -> {
                                    binding.editText.append("****")
                                    binding.editText.setSelection(curPosition + 2)
                                }
                                1 -> {
                                    binding.editText.append("**")
                                    binding.editText.setSelection(curPosition + 1)
                                }
                                2 -> {
                                    binding.editText.append("******")
                                    binding.editText.setSelection(curPosition + 3)
                                }
                                3 -> {
                                    binding.editText.append("~~~~")
                                    binding.editText.setSelection(curPosition + 2)

                                }
                                4 -> {
                                    binding.editText.append("<sup></sup>")
                                    binding.editText.setSelection(curPosition + 5)
                                }
                                5 -> {
                                    binding.editText.append("<sub></sub>")
                                    binding.editText.setSelection(curPosition + 5)
                                }
                            }
                            binding.editText.showKeyBoard(activity)

                        }
                        .show()
            }

            binding.btnQuote -> {
                val curPosition = binding.editText.selectionStart
                binding.editText.append(">")
                binding.editText.setSelection(curPosition + 1)
                binding.editText.showKeyBoard(activity)

            }

            binding.btnCode -> {
                val curPosition = binding.editText.selectionStart
                binding.editText.append("```\n\n\n```")
                binding.editText.setSelection(curPosition + 4)
                binding.editText.showKeyBoard(activity)
            }

            binding.btnImage -> {
                val curPosition = binding.editText.selectionStart
                listener.onAddImageClick(curPosition)
            }

            binding.btnUrl -> {
                val dialogView = LayoutInflater.from(context)
                        .inflate(R.layout.layout_add_url, null)
                val etDialogTitle = dialogView.findViewById<EditText>(R.id.et_title)
                val etDialogAddress = dialogView.findViewById<EditText>(R.id.et_address)
                AlertDialog.Builder(context)
                        .setTitle(R.string.add_url)
                        .setView(dialogView)
                        .setPositiveButton(R.string.OK) { _, _ ->
                            val title = etDialogTitle.text.toString()
                            val address = etDialogAddress.text.toString()
                            if (title.isNotBlank() && address.isNotBlank()) {
                                addUrl(title, address)
                            }
                        }
                        .setNeutralButton(R.string.cancel, null)
                        .show()
            }

            binding.btnLine -> {
                val curPosition = binding.editText.selectionStart
                binding.editText.append("----\n\n")
                binding.editText.setSelection(curPosition + 6)
            }

            binding.btnTop -> {
                gotoTop()
            }

            binding.btnBottom -> {
                gotoBottom()
            }

//            binding.btnUndo -> {
//                undo()
//
//            }
//
//            binding.btnRedo -> {
//                redo()
//            }
        }
    }

    fun redo() {
        if (cacheText != null) {
            binding.editText.setText(cacheText)
            binding.editText.setSelection(cacheText!!.length)
        }
    }

    fun undo() {
        cacheText = binding.editText.text.toString()
        if (cache.size > 0) {
            binding.editText.setText(cache[cache.lastIndex])
            cache.removeAt(cache.lastIndex)
            binding.editText.setSelection(cache[cache.lastIndex].length)
        }
    }

    fun gotoTop() {
        binding.editText.setSelection(0)
    }

    fun addMarkdown(syntax: String) {
        val pos = getInsertPosition()
        val text = binding.editText.text.toString()
        binding.editText.setText(text.substring(0, pos) + syntax + text.substring(pos, text.length))
        binding.editText.setSelection(pos + syntax.length)
    }

    fun setTheme() {
        isNormal = !isNormal
        setNight(isNormal)
    }

    fun setNight(isNormal: Boolean) {
        if (!isNormal) {
            binding.editText.setTextColor(Color.WHITE)
            binding.editText.setBackgroundColor(context.getColor(R.color.colorBottomBgColor))
        } else {
            binding.editText.setTextColor(context.getColor(R.color.colorBottomBgColor))
            binding.editText.setBackgroundColor(Color.WHITE)
        }
    }

    //todo 添加视频标签
    fun addVideoPoster(title: String, source: String, src: String) {
        isEditorView = true
        val syntax = "\np{$title}[$source]($src)\n"
        addMarkdown(syntax)
        saveMarkdownFile(outputFile!!)
        binding.editText.requestFocus()
    }

    fun addVideo(title: String, source: String) {
        isEditorView = true
        val syntax = "\nv{$title}[$source]\n"
        addMarkdown(syntax)
        saveMarkdownFile(outputFile!!)
        binding.editText.requestFocus()
    }

    fun addAudio(title: String, source: String) {
        isEditorView = true
        val syntax = "\ni{$title}[$source]\n"
        addMarkdown(syntax)
        saveMarkdownFile(outputFile!!)
        binding.editText.requestFocus()
    }


    fun addUrl(title: String = "", url: String = "") {
        isEditorView = true
        binding.editText.append("\n[$title]($url)\n\n")
        gotoBottom()
        saveMarkdownFile(outputFile!!)
        binding.editText.requestFocus()
    }

    fun addImageUrl(title: String, url: String, imagePath: String) {
        isEditorView = true
        val syntax = "\ni{$title}[$imagePath]($url)\n"
        //val syntax = "\n<a href=\"$url\"><img src=\"$imagePath\">$title</img></a>\n"
        addMarkdown(syntax)
        //binding.editText.setSelection(getInsertPosition())
        //binding.editText.append("\n<a href=\"$url\"><img src=\"$imagePath\">$title</img></a>\n")
        saveMarkdownFile(outputFile!!)
        binding.editText.requestFocus()
    }

    fun addColorText(text: String, isBool: Boolean, isItalic: Boolean, color: String, textSize: String) {
        val sb = StringBuilder()
        sb.append("\nc{title}")
        if (isBool) {
            sb.append("b")
        }
        if (isItalic) {
            sb.append("i")
        }

        if (color.isNotBlank()) {
            sb.append("#$color")
        }

        if (textSize.isNotBlank()) {
            sb.append("${textSize}pt")
        }
        sb.append("\n")

        val syntax = sb.toString()
        addMarkdown(syntax)
        saveMarkdownFile(outputFile!!)
        requestFocus()
    }

    fun addVideoMark(title: String, imagePath: String, filePath: String, position: Int) {
        val syntax = "\ni{$title}[$imagePath]($filePath#$position)"
        addMarkdown(syntax)
        saveMarkdownFile(outputFile!!)

    }

    fun EditText.showKeyBoard(activity: Activity) {
        if (isKeyboardConnected(activity))
            return
        this.postDelayed(Runnable {
            this.requestFocus()
            val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            inputManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
        }, 200)
    }

    fun addImage(imagePath: String, position: Int = -1) {
        Log.i("NoteEditor", imagePath)
        val name = getFileName(imagePath)
        val syntax = "\n![$name]($imagePath)\n\n"
        addMarkdown(syntax)
        //binding.editText.append("\n![$name]($imagePath)\n\n")
        saveMarkdownFile(outputFile!!)
    }

    fun getFileName(filePath: String): String {
        return filePath.substringAfterLast("/").substringBeforeLast(".")
    }

    fun setText(content: String) {
        binding.editText.setText(content)
    }

    fun setFocus() {
        binding.editText.requestFocus()
        gotoBottom()
    }

    fun gotoBottom() {
        binding.editText.setSelection(binding.editText.text.length)
    }

    fun isEmpty(): Boolean {
        return binding.editText.text.isBlank()
    }

    fun save() {
        saveMarkdownFile(outputFile!!)
    }


    fun getInsertPosition(): Int {
        val curPosition = binding.editText.selectionStart
        val text = binding.editText.text.toString()
        if (text.isEmpty()) {
            return 0
        } else {
            val aText = text.substring(curPosition, text.length)
            return curPosition + aText.substringBefore('\n').length
        }
    }

    fun onlyTitle(s: String): Boolean {
        val text = binding.editText.text.toString().replace("\n", "").replace(" ", "")
        val title = s.replace("\n", "").replace(" ", "")
        return text == title
    }


}


